package com.zlzlib.librxoknet.pro;

import android.os.SystemClock;


import com.zlzlib.librx.ProgressInfo;
import com.zlzlib.librx.listener.ProgressListener;

import java.io.IOException;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;

/**
 * 带进度的请求体  上传
 * Created by zlz on 2019/3/1.
 */
public class ProRequestBody extends RequestBody {

    private final RequestBody delegate;
    private final ProgressListener<Buffer> listener;
    private final long freshTime;
    private final ProgressInfo<Buffer> info;

    public ProRequestBody(RequestBody delegate, ProgressListener<Buffer> listener, long freshTime) {
        this.delegate = delegate;
        this.listener = listener;
        this.freshTime = freshTime;
        info = new ProgressInfo<>(System.currentTimeMillis());
        info.setContentLength(contentLength());
        //第一次直接返回总长度
        AndroidSchedulers.mainThread().scheduleDirect(() -> ProRequestBody.this.listener.updateDown(info));
    }

    @Override
    public MediaType contentType() {
        return delegate.contentType();
    }

    @Override
    public long contentLength() {
        try {
            return delegate.contentLength();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return -1;
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        CountingSink countingSink = new CountingSink(sink);
        BufferedSink bufferedSink = Okio.buffer(countingSink);
        delegate.writeTo(bufferedSink);
        bufferedSink.flush();
    }

    private final class CountingSink extends ForwardingSink {

        //当前数据总大小
        private long currLength = 0;
        private long lastRefreshTime = SystemClock.elapsedRealtime();  //最后一次刷新的时间
        private long tempSize = 0L;

        public CountingSink(Sink delegate) {
            super(delegate);
        }

        @Override
        public void write(Buffer source, long byteCount) throws IOException {
            super.write(source, byteCount);
            if (listener == null || info.isFinish()) {
                return;
            }
            currLength += byteCount;
            tempSize += byteCount;
            //判断刷新时间
            long curTime = SystemClock.elapsedRealtime();
            long intervalTime = curTime - lastRefreshTime;
            if (currLength >= info.getContentLength() || intervalTime >= freshTime) {
                //加载完成
                info.setData(source);
                info.setEachBytes(tempSize);
                info.setCurrentBytes(currLength);
                info.setIntervalTime(intervalTime);
                info.setFinish(currLength >= info.getContentLength());
                //发送到主线程
                AndroidSchedulers.mainThread().scheduleDirect(() -> listener.updateDown(info));
                listener.updateUp(info);
                tempSize = 0;
                lastRefreshTime = curTime;
            }
        }

    }

}
